package Szadoban;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;

/**
 * Configuration file parser
 */
public class Reader {
	
	/**
	 * Size of each square element in px
	 */
	private final int OFFSET = 40;
	
	/**
	 * Size of margin in px
	 */
	private final int MARGIN = 50;
	
	/**
	 * Difficulty level
	 */
	private int difficulty;
	
	/**
	 * Current level
	 */
	private int level;
	
	/**
	 * Number of boxes
	 */
	private int nrOfBoxes;
	
	/**
	 * Current map structure
	 */
	private String map;
	
	/**
	 * Array of walls existing in the current map
	 */
	private ArrayList<Wall> walls = new ArrayList<>();
	
	/**
	 * Array of boxes existing in the current map
	 */
	private ArrayList<Box> boxes = new ArrayList<>();
	
	/**
	 * Array of destinations existing in the current map
	 */
	private ArrayList<Destination> destinations = new ArrayList<>();
	
	/**
	 * Configuration file
	 */
	private File f = new File("config.properties");
	private Properties p = new Properties();
	
	/**
	 * List of all elements in the current map
	 */
	private ArrayList<Element>elements = new ArrayList<Element>();
	
	/**
	 * Instance of the player
	 */
	private Player Szadoban;
	
	/**
	 * Function adds all existing elements to one array
	 */
	private void setElements(){
		elements.addAll(walls);
		elements.addAll(boxes);
		elements.addAll(destinations);
		elements.add(Szadoban);
	}
	
	/**
	 * @return ArrayList of all elements in the current map
	 */
	public ArrayList<Element> getElements(){
		return elements;
	}
	
	/**
	 * @return ArrayList of all walls in the current map
	 */
	public ArrayList<Wall> getWalls() {
		return walls;
	}
	
	/**
	 * @return ArrayList of all boxes in the current map
	 */
	public ArrayList<Box> getBoxes() {
		return boxes;
	}
	
	/**
	 * Construction of the configuration files reader
	 */
	public Reader(){ //arg String name_input, File f
		load();
		readConfig();
		setElements();
	}
	
	/**
	 * Loads properties of a configuration file
	 */
	public void load(){
		InputStream input;
		try{
			input = new FileInputStream(f);
			p.load(input);
		} catch(FileNotFoundException e) {
			System.out.println("[ERROR] File not found");
		} catch(IOException e) {
			System.out.println("[ERROR])IO Exception");
		}	
	}
	
	/**
	 * Function reads a configuration file
	 */
	private final void readConfig(){
		
		Box box;
		Wall wall;
		Destination destination;
		
		int x = MARGIN;
		int y = 5*MARGIN;
		
		this.setDiff(Integer.parseInt(p.getProperty("DIFF")));
		this.map = p.getProperty("MAP");
		this.setLevel(Integer.parseInt(p.getProperty("LEVEL")));
		this.setBoxes(Integer.parseInt(p.getProperty("BOXES")));
		
		for(int i = 0; i < map.length(); i++){
			char element = map.charAt(i);
			
			switch(element){
			case '\n' :
				y += OFFSET;
				x = MARGIN;
				break;
			case '.' :
				x += OFFSET;
				break;
			case 'X' :
				wall = new Wall(x,y);
				walls.add(wall);
				x += OFFSET;
				break;
			case '?' :
				destination = new Destination(x,y);
				destinations.add(destination);
				x += OFFSET;
				break;
			case '*' :
				box = new Box(x,y);
				boxes.add(box);
				x += OFFSET;
				break;
			case '@' :
				Szadoban = new Player(x,y);
				x += OFFSET;
				break;
			case ' ' :
				x += OFFSET;
				break;
			default :
				continue;
			}
		}
	}

	/**
	 * 
	 * @return Difficulty level
	 */
	public int getDiff() {
		return difficulty;
	}

	public void setDiff(int difficulty) {
		this.difficulty = difficulty;
	}
	
	/**
	 * 
	 * @return number of current level
	 */
	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}
	
	public int getBoxesNumber(){
		return nrOfBoxes;
	}
	
	public void setBoxes(int boxes){
		this.nrOfBoxes = boxes;
	}
	
	/**
	 * 
	 * @return Player object
	 */
	public Player getPlayer(){
		return Szadoban;
	}
}
